﻿/*
* Slickflow 工作流引擎遵循LGPL协议，也可联系作者商业授权并获取技术支持；
* 除此之外的使用则视为不正当使用，请您务必避免由此带来的商业版权纠纷。
* 
The Slickflow project.
Copyright (C) 2014  .NET Workflow Engine Library

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, you can access the official
web page about lgpl: https://www.gnu.org/licenses/lgpl.html
*/

using System;
using Sharp.Domain.PlatformBoundedContext.WorkFlowModule.Aggregates;
using Sharp.Domain.PlatformBoundedContext.WorkFlowModule.Engine.Business.EntitySQLServer;
using Sharp.Domain.PlatformBoundedContext.WorkFlowModule.Engine.Common;
using Sharp.Domain.PlatformBoundedContext.WorkFlowModule.Engine.Xpdl;

//using Slickflow.Data;

namespace Sharp.Domain.PlatformBoundedContext.WorkFlowModule.Engine.Core.Pattern
{
    /// <summary>
    /// 任务节点执行器
    /// </summary>
    internal class NodeMediatorTask : NodeMediator
    {
        internal NodeMediatorTask(ActivityForwardContext forwardContext )
            : base(forwardContext)
        {

        }

        internal NodeMediatorTask( )
            : base( )
        {

        }

        /// <summary>
        /// 执行普通任务节点
        /// 1. 当设置任务完成时，同时设置活动完成
        /// 2. 当实例化活动数据时，产生新的任务数据
        /// </summary>
        internal override void ExecuteWorkItem()
        {
            try
            {
                //执行Action列表
                ExecteActionList(ActivityForwardContext.Activity.ActionList,
                    ActivityForwardContext.ActivityResource.AppRunner.ActionMethodParameters);

                //完成当前的任务节点
                bool canContinueForwardCurrentNode = CompleteWorkItem(ActivityForwardContext.TaskView,
                    ActivityForwardContext.ActivityResource );

                if (canContinueForwardCurrentNode)
                {
                    bool isJumpforward = ActivityForwardContext.TaskView == null ? true : false;
                    //获取下一步节点列表：并继续执行
                    ContinueForwardCurrentNode(isJumpforward);
                }
            }
            catch 
            {
                throw;
            }
        }

        /// <summary>
        /// 完成任务实例
        /// </summary>
        /// <param name="taskView">任务视图</param>
        /// <param name="activityResource">活动资源</param>
                
        internal bool CompleteWorkItem(TaskEntity taskView,
            ActivityResource activityResource )
        {
            bool canContinueForwardCurrentNode = true;

            WfAppRunner runner = new WfAppRunner
            {
                UserID = activityResource.AppRunner.UserID,         //避免taskview为空
                UserName = activityResource.AppRunner.UserName
            };

            //流程强制拉取向前跳转时，没有运行人的任务实例
            if (taskView != null)
            {
                //完成本任务，返回任务已经转移到下一个会签任务，不继续执行其它节点
                base.TaskManager.Complete(taskView.Id, activityResource.AppRunner);
            }

            //设置活动节点的状态为完成状态
            base.ActivityInstanceManager.Complete(base.Linker.FromActivityInstance.Id,
                activityResource.AppRunner );

            base.Linker.FromActivityInstance.ActivityState = ActivityStateEnum.Completed;

            return canContinueForwardCurrentNode;
        }

        /// <summary>
        /// 创建活动任务转移实例数据
        /// </summary>
        /// <param name="toActivity">活动</param>
        /// <param name="processInstance">流程实例</param>
        /// <param name="fromActivityInstance">开始活动实例</param>
        /// <param name="transitionGUID">转移GUID</param>
        /// <param name="transitionType">转移类型</param>
        /// <param name="flyingType">跳跃类型</param>
        /// <param name="activityResource">活动资源</param>
        
        internal override void CreateActivityTaskTransitionInstance(ActivityEntity toActivity,
            ProcessInstanceEntity processInstance,
            ActivityInstanceEntity fromActivityInstance,
            string transitionGUID,
            TransitionTypeEnum transitionType,
            TransitionFlyingTypeEnum flyingType,
            ActivityResource activityResource )
        {
            Boolean isParallel = false;
            if (fromActivityInstance.ActivityType == ActivityTypeEnum.GatewayNode)
            {
                //并发多实例分支判断(AndSplit Multiple)
                var processModel = new ProcessModel(processInstance.ProcessGUID, processInstance.Version);
                var activityNode = processModel.GetActivity(fromActivityInstance.ActivityGUID);
                if (activityNode.GatewaySplitJoinType == GatewaySplitJoinTypeEnum.Split
                    && activityNode.GatewayDirectionType == GatewayDirectionEnum.AndSplitMI)
                {
                    isParallel = true;
                }
            }


            if (isParallel)
            {
                //并行多实例
                var entity = new ActivityInstanceEntity();
                var plist = activityResource.NextActivityPerformers[toActivity.ActivityGUID];
                for (var i = 0; i < plist.Count; i++)
                {
                    entity = base.CreateActivityInstanceObject(toActivity, processInstance, activityResource.AppRunner);
                    entity.AssignedToUserIDs = plist[i].UserID;
                    entity.AssignedToUserNames = plist[i].UserName;
                    entity.ActivityState = ActivityStateEnum.Ready;
                    //插入活动实例数据
                    entity.Id = base.ActivityInstanceManager.Insert(entity);
                    //插入任务
                    base.TaskManager.Insert(entity, plist[i], activityResource.AppRunner);
                    //插入转移数据
                    InsertTransitionInstance(processInstance,
                        transitionGUID,
                        fromActivityInstance,
                        entity,
                        transitionType,
                        flyingType,
                        activityResource.AppRunner );
                }
            }
            else
            {
                //普通任务节点
                var toActivityInstance = base.CreateActivityInstanceObject(toActivity, processInstance, activityResource.AppRunner);

                //进入运行状态
                toActivityInstance.ActivityState = ActivityStateEnum.Ready;
                toActivityInstance.AssignedToUserIDs = GenerateActivityAssignedUserIDs(
                    activityResource.NextActivityPerformers[toActivity.ActivityGUID]);
                toActivityInstance.AssignedToUserNames = GenerateActivityAssignedUserNames(
                    activityResource.NextActivityPerformers[toActivity.ActivityGUID]);

                //插入活动实例数据
                base.ActivityInstanceManager.Insert(toActivityInstance);

                //插入任务数据
                base.CreateNewTask(toActivityInstance, activityResource);

                //插入转移数据
                InsertTransitionInstance(processInstance,
                    transitionGUID,
                    fromActivityInstance,
                    toActivityInstance,
                    transitionType,
                    flyingType,
                    activityResource.AppRunner );
            }
        }
    }
}
